package org.bee.service;

import jakarta.annotation.Resource;
import org.bee.enums.ElementType;
import org.bee.enums.IsDelete;
import org.bee.input.ElementSearchVo;
import org.bee.mappers.ElementMapper;
import org.bee.mappers.ext.ElementExtMapper;
import org.bee.model.Element;
import org.bee.model.ElementExample;
import org.bee.output.ElementOut;
import org.bee.output.Menus;
import org.bee.output.Meta;
import org.bee.string.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
public class ElementService {
    @Resource
    private ElementExtMapper elementExtMapper;

    @Resource
    private ElementMapper elementMapper;

    /**
     * 获取用户菜单权限
     * @param userId 用户id
     * @return 菜单列表
     */
    public List<Element> getMenusByUserId(String userId){
        return elementExtMapper.getElementByUserId(userId, ElementType.MENU.getCode());
    }

    public HashMap<String, List<String>> getAuthButtonByUserId(String userId){
        HashMap<String, List<String>> result = new HashMap<>();
        //获取用户拥有的所有的元素信息
        List<Element> elementByUserId = elementExtMapper.getElementByUserId(userId, null);
        //拿到所有的菜单
        List<Element> list = elementByUserId.stream().filter(element -> ElementType.MENU.getCode()
                .equals(element.getType())).toList();
        for (Element element : list) {
            //拿到当前菜单下的所有按钮
            List<Element> elementList = elementByUserId.stream().filter(elementin -> (element.getElementId()
                    .equals(elementin.getParentId())&&ElementType.BUTTON.getCode().equals(elementin.getType()))).toList();
            //拿到当前菜单下的所有按钮code
            List<String> buttonList = elementList.stream().map(Element::getCode).toList();
            if(!buttonList.isEmpty()){
                result.put(element.getName(), buttonList);
            }
        }
        return result;
    }
    /**
     * 获取角色按钮权限
     * @param roleId 用户roleId
     * @return 按钮列表
     */
    public List<Element> getElementByRoleId(String roleId){
        return elementExtMapper.getElementByRoleId(roleId, null);
    }

    /**
     * 获取菜单树
     * @param userId 用户id
     * @param roleId 角色Id
     * @param allTypeFlag 是否获取所有类型页面元素
     * @return 菜单树
     */
    public List<Menus> getMenusTree(String userId, String roleId,boolean allTypeFlag){
        List<Menus> resultMenusList = new ArrayList<>();
        List<Element> menuList;
        if(allTypeFlag){
            if(!StringUtils.isEmpty(roleId)){
                menuList = this.getElementByRoleId(roleId);
            }else{
                ElementExample example = new ElementExample();
                ElementExample.Criteria criteria = example.createCriteria();
                criteria.andIsDeletedEqualTo(IsDelete.FALSE.getCode());
                menuList = elementMapper.selectByExample(example);
            }
        }else{
            menuList = this.getMenusByUserId(userId);
        }
        List<Element> rootList = menuList.stream().filter(menu -> StringUtils.isEmpty(menu.getParentId())).toList();
        for (Element root : rootList) {
            Menus menus = new Menus();
            BeanUtils.copyProperties(root, menus);
            Meta meta = new Meta();
            BeanUtils.copyProperties(root, meta);
            meta.setIsHide(root.getIsHide());
            meta.setIsKeepAlive(root.getIsKeepAlive());
            meta.setIsAffix(root.getIsAffix());
            meta.setIsFull(root.getIsFull());
            menus.setMeta(meta);
            resultMenusList.add(menus);
        }
        getChildren(resultMenusList, menuList);
        return resultMenusList;
    }

    /**
     * 递归获取子菜单
     * @param resultMenusList 菜单结果列表
     * @param menuList 用户拥有的所有菜单
     */
    private void getChildren(List<Menus> resultMenusList, List<Element> menuList) {
        for (Menus menus : resultMenusList) {
            List<Element> childrens = menuList.stream().filter(
                    menu -> null!=menu.getParentId()&&menu.getParentId().equals(menus.getElementId())).toList();
            if(!childrens.isEmpty()){
                List<Menus> childrenMenus = new ArrayList<>();
                for (Element children : childrens) {
                    Menus childMenus = new Menus();
                    BeanUtils.copyProperties(children, childMenus);
                    Meta childMeta = new Meta();
                    BeanUtils.copyProperties(children, childMeta);
                    childMeta.setIsHide(children.getIsHide());
                    childMeta.setIsKeepAlive(children.getIsKeepAlive());
                    childMeta.setIsAffix(children.getIsAffix());
                    childMeta.setIsFull(children.getIsFull());
                    childMenus.setMeta(childMeta);
                    childrenMenus.add(childMenus);
                }
                menus.setChildren(childrenMenus);
                getChildren(childrenMenus, menuList);
            }
        }
    }
    private void getChildrenElement(List<ElementOut> resultList,List<Element> elementList){
        for (ElementOut elementOut : resultList) {
            List<Element> childrens = elementList.stream().filter(element ->null!=element.getParentId()&&
                    element.getParentId().equals(elementOut.getElementId())).toList();
            if(!childrens.isEmpty()){
                List<ElementOut> childrenElement = new ArrayList<>();
                for (Element children : childrens) {
                    ElementOut childrenElementOut = new ElementOut();
                    BeanUtils.copyProperties(children, childrenElementOut);
                    childrenElementOut.setTypeName(ElementType.getCodeMean(children.getType()));
                    childrenElementOut.setFull(children.getIsFull());
                    childrenElementOut.setHide(children.getIsHide());
                    childrenElementOut.setAffix(children.getIsAffix());
                    childrenElementOut.setKeepAlive(children.getIsKeepAlive());
                    childrenElement.add(childrenElementOut);
                }
                elementOut.setChildren(childrenElement);
                getChildrenElement(childrenElement, elementList);
            }
        }
    }
    /**
     * 查询页面元素表
     * @param elementSearchVo 页面元素表查询参数
     * @return 页面元素表列表
     */
    public List<ElementOut> selectTree(ElementSearchVo elementSearchVo) {
        List<ElementOut> resultList = new ArrayList<>();
        ElementExample elementExample = new ElementExample();
        ElementExample.Criteria criteria = elementExample.createCriteria();
        if (StringUtils.isNotEmpty(elementSearchVo.getTitle())) {
            criteria.andTitleLike("%"+elementSearchVo.getTitle()+"%");
        }
        if (StringUtils.isNotEmpty(elementSearchVo.getType())) {
            criteria.andTypeEqualTo(elementSearchVo.getType());
        }
        elementExample.setOrderByClause("order_num asc");
        criteria.andIsDeletedEqualTo(IsDelete.FALSE.getCode());
        List<Element> elementList = elementMapper.selectByExample(elementExample);
        List<Element> rootList =elementList.stream().filter(element -> StringUtils.isEmpty(element.getParentId())).toList();
        for (Element element : rootList) {
            ElementOut elementOut = new ElementOut();
            BeanUtils.copyProperties(element, elementOut);
            elementOut.setTypeName(ElementType.getCodeMean(element.getType()));
            elementOut.setFull(element.getIsFull());
            elementOut.setHide(element.getIsHide());
            elementOut.setAffix(element.getIsAffix());
            elementOut.setKeepAlive(element.getIsKeepAlive());
            resultList.add(elementOut);
        }
        getChildrenElement(resultList, elementList);
        return resultList;
    }

    /**
     * 插入页面元素表
     * @param element 页面元素表实体
     * @return 插入结果
     */
    public int insert(Element element) {
        return elementMapper.insert(element);
    }

    /**
     * 删除页面元素表
     * @param elementId 页面元素表id
     * @return 删除结果
     */
    public int delete(String elementId,Boolean isDelete) {
        if(isDelete){
            return elementMapper.deleteByPrimaryKey(elementId);
        }else{
            Element element = new Element();
            element.setElementId(elementId);
            element.setIsDeleted(true);
            return elementMapper.updateByPrimaryKeySelective(element);
        }
    }

    /**
     * 根据主键更新页面元素表
     * @param element 页面元素表实体
     * @return 更新结果
     */
    public int update(Element element) {
        return elementMapper.updateByPrimaryKeySelective(element);
    }

    /**
     * 根据主键查询元素表
     *
     * @param id 元素表id
     * @return 元素结果
     */
    public Element selectById(String id) {
        return elementMapper.selectByPrimaryKey(id);
    }

    /**
     * 根据父级id查询元素表
     *
     * @param id 元素表父级id
     * @return 元素结果
     */
    public List<Element> selectByPId(String id) {
        ElementExample elementExample = new ElementExample();
        ElementExample.Criteria criteria = elementExample.createCriteria();
        criteria.andParentIdEqualTo(id);
        criteria.andIsDeletedEqualTo(IsDelete.FALSE.getCode());
        return elementMapper.selectByExample(elementExample);
    }
}
